import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

@SuppressWarnings("serial")
public class Configuration extends JPanel {
   MainPanel mainpanel;
   
	public Configuration(MainPanel mainpanel){
		this.mainpanel = mainpanel;
		sliderPanel sliderPanel = new sliderPanel();
		TitledBorder b = new TitledBorder("Speed");
		b.setTitleColor(Color.RED);
		sliderPanel.setBorder(b);
		
		algorithmPanel policeAlgorithm = new algorithmPanel(false);
		policeAlgorithm.setBorder(new TitledBorder("Algorithm Settings For Police"));
		policeAlgorithm.combo.removeItemAt(2);
		policeAlgorithm.remove(policeAlgorithm.N);
		add(sliderPanel);
		add(policeAlgorithm);
		
		algorithmPanel racerAlgorithm = new algorithmPanel(true);
		//racerAlgorithm.setBorder(new TitledBorder("Algorithm Settings For Racer"));
		//racerAlgorithm.combo.removeItemAt(1);
		//racerAlgorithm.combo.removeItemAt(0);
		racerAlgorithm.combo.setSelectedIndex(2);
		
		add(racerAlgorithm);
		setLayout(new GridLayout(3,1,0,0));
		setPreferredSize(new Dimension(250,400));
	}

	public void showWindow(){
		setVisible(true);
	}
	
	class algorithmPanel extends JPanel implements ActionListener , DocumentListener{
		JTextField N;
		JTextField alpha,gamma,epsilon;
		JComboBox combo;
		String algList[];
		JRadioButtonMenuItem Static,dynamic;
		boolean isRacer;
		public algorithmPanel(boolean isRacer){
			
			this.isRacer = isRacer;
			Static  = new JRadioButtonMenuItem("Static");
			dynamic = new JRadioButtonMenuItem("Dynamic");
		    algList = new String[3];
			setLayout(new BorderLayout());
			algList[0] = "Sarsa";
			algList[1] = "QLearning";
			algList[2] = "DynaQ";
			combo = new JComboBox(algList);
			combo.setSelectedIndex(0);
			combo.addActionListener(this);
			JPanel variable = new JPanel(new GridLayout(2,3));
			ButtonGroup group = new ButtonGroup();
			JLabel s1 = new JLabel("Alpha");
			JLabel s2 = new JLabel("Gamma");
			JLabel s3 = new JLabel("Epsilon");
            
			variable.add(s1);
			variable.add(s2);
			variable.add(s3);
            
			alpha = new JTextField("0.5");
			gamma = new JTextField("0.5");
		    epsilon = new JTextField("0.1");
		    N = new JTextField("10");
			N.setBorder(new TitledBorder("N"));
			
		    alpha.getDocument().addDocumentListener(this);
		    gamma.getDocument().addDocumentListener(this);
		    epsilon.getDocument().addDocumentListener(this);
		    N.getDocument().addDocumentListener(this);
		    
			variable.add(alpha);
			variable.add(gamma);
			variable.add(epsilon);
			
			group.add(Static);
			group.add(dynamic);
			Static.setSelected(true);
			Static.addActionListener(this);
			dynamic.addActionListener(this);
			add(combo,BorderLayout.NORTH);
			add(variable,BorderLayout.SOUTH);
			add(Static,BorderLayout.EAST);
			add(dynamic,BorderLayout.WEST);
			add(N,BorderLayout.CENTER);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			String s = initializeAlgorithm();
			
			if(e.getSource()==Static){
				this.epsilon.setEnabled(true);
				mainpanel.temporal.isEpsilonDynamic = false;
				s+=" I am static";
			}
			else if(e.getSource()==dynamic){
				this.epsilon.setEnabled(false);
				mainpanel.temporal.isEpsilonDynamic = true;
				s+=" I am dynamic";
			}
			System.out.println(s + "\t" + mainpanel.temporal.alpha +"\t"+ mainpanel.temporal.gamma +"\t"+ mainpanel.temporal.epsilon);
			
			assingAlgorithmsToAgents();
		}
		public String initializeAlgorithm(){
			double alpha,gamma,epsilon;
			int n;
			try{
				alpha = Double.parseDouble(this.alpha.getText());
			}
			catch(Exception ex){
				alpha = 0.5;
			}
			try{
				gamma = Double.parseDouble(this.gamma.getText());
			}
			catch(Exception ex){
				gamma = 0.5;
			}
			try{
				epsilon = Double.parseDouble(this.epsilon.getText());
			}
			catch(Exception ex){
				epsilon = 0.1;
			}
		
			try{
				n = Integer.parseInt(N.getText());
			}
			catch(Exception ex){
					n = 10;
			}
			
			String s = (String)combo.getSelectedItem();
			
			if(s.equals(algList[0])){
				mainpanel.temporal = new Sarsa(alpha,gamma,epsilon,0);
				if(mainpanel.temporal.isEpsilonDynamic){
					mainpanel.temporal.isEpsilonDynamic = true;
				}
				else{
					mainpanel.temporal.isEpsilonDynamic = false;
				}
			}
			else if(s.equals(algList[1])){
				mainpanel.temporal = new QLearning(alpha,gamma,epsilon,0);
				if(mainpanel.temporal.isEpsilonDynamic){
					mainpanel.temporal.isEpsilonDynamic = true;
				}
				else{
					mainpanel.temporal.isEpsilonDynamic = false;
				}
			}
			else if(isRacer && s.equals(algList[2])){
				mainpanel.temporal = new DynaQ(alpha,gamma,epsilon,0,n);
				if(mainpanel.temporal.isEpsilonDynamic){
					mainpanel.temporal.isEpsilonDynamic = true;
				}
				else{
					mainpanel.temporal.isEpsilonDynamic = false;
				}
			}
			return (String)combo.getSelectedItem();
		}
		@SuppressWarnings("static-access")
		public void assingAlgorithmsToAgents(){
			if(isRacer)
				for(int i = 0;i<3;i++){
					if(mainpanel.threadRacer[i]!=null){
						if(mainpanel.temporal instanceof Sarsa)
							mainpanel.racer[i].temporal = new Sarsa(mainpanel.temporal.alpha,mainpanel.temporal.gamma,mainpanel.temporal.epsilon,0);
						else if(mainpanel.temporal instanceof QLearning)
							mainpanel.racer[i].temporal = new QLearning(mainpanel.temporal.alpha,mainpanel.temporal.gamma,mainpanel.temporal.epsilon,0);
						else
							mainpanel.racer[i].temporal = new DynaQ(mainpanel.temporal.alpha,mainpanel.temporal.gamma,mainpanel.temporal.epsilon,0,mainpanel.temporal.N);
					}
				}
			else
				if(mainpanel.polStation!=null)	{
					if(mainpanel.temporal instanceof Sarsa)
						mainpanel.polStation.temporal = new Sarsa(mainpanel.temporal.alpha,mainpanel.temporal.gamma,mainpanel.temporal.epsilon,0);
					else if(mainpanel.temporal instanceof QLearning)
						mainpanel.polStation.temporal = new QLearning(mainpanel.temporal.alpha,mainpanel.temporal.gamma,mainpanel.temporal.epsilon,0);
					/*else
						mainpanel.polStation.temporal = new DynaQ(mainpanel.temporal.alpha,mainpanel.temporal.gamma,mainpanel.temporal.epsilon,0);
					*/
				}
		}
		@Override
		public void changedUpdate(DocumentEvent e) {
		}
		@Override
		public void insertUpdate(DocumentEvent e) {
			String s = initializeAlgorithm();		
			if(mainpanel.temporal.isEpsilonDynamic)
				System.out.println(s+" I am dynamic" + "\t" + mainpanel.temporal.alpha +"\t"+ mainpanel.temporal.gamma +"\t"+ mainpanel.temporal.epsilon);
			else
				System.out.println(s+" I am static" + "\t" + mainpanel.temporal.alpha +"\t"+ mainpanel.temporal.gamma +"\t"+ mainpanel.temporal.epsilon);
			assingAlgorithmsToAgents();
	
		}
		@Override
		public void removeUpdate(DocumentEvent e) {
			// TODO Auto-generated method stub
			
		}
	}
	
	class sliderPanel extends JPanel implements ChangeListener{
		 JSlider slider  = new JSlider(JSlider.HORIZONTAL,10,100,20);
		
		public sliderPanel(){
			setBackground(Color.BLUE);
			setLayout(new BorderLayout());
			slider.setBackground(Color.cyan);
			slider.addChangeListener(this);
			slider.setPaintLabels(true);
			slider.setPaintTicks(true);
			slider.setMajorTickSpacing(10);
			slider.setMinorTickSpacing(1);
			add(slider,BorderLayout.CENTER);
	
		}

		@Override
		public void stateChanged(ChangeEvent arg0) {
			//evaluates agents' speed and changes sthem
 			JSlider source = (JSlider)arg0.getSource();
			int change =(int)source.getValue();
			Component.volume=(int) (Component.maxVolume/(Math.pow(	2, change/10)));
		
		}
	}
}